package com.guapi.util;

import cn.hutool.core.collection.CollectionUtil;
import com.guapi.dao.IpRecord;
import com.guapi.exception.SelfException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class IpUtils {

    @Autowired
    private RedisTemplate redisTemplate;

    private HashMap<String, Integer> recordToBeBanIp = new HashMap<>();


    public void recordIpIn(HttpServletRequest request) throws SelfException {
        String ip = request.getRemoteHost();
        String ipKey = RedisUtil.getInWebIp(ip);
        Integer count = recordToBeBanIp.get(ip);
        Map<String, Long> inIps = getInIps();
        long now = System.currentTimeMillis();
        if (!inIps.values().contains(ip)) {
            inIps.put(ip, now);
        }
        IpRecord ipRecord = new IpRecord();
        ipRecord.setIp(ip);
        Map<String, List<IpRecord>> ipInRecord = new HashMap<>();
        List<IpRecord> ipLists = new ArrayList<>();
        if (judgeIpIsBan(ip)) {
            throw new SelfException("500", "THIS IP:" + ip + " IS BANNED!");
        }
        if (count != null && count > 3) {
            List<String> banIps = getBanIps();
            banIps.add(ip);
            redisTemplate.opsForValue().set(RedisUtil.getBanIp(), banIps);
            throw new SelfException("500", "THIS IP :" + ip + " IS BANNED!");
        }
        if (redisTemplate.hasKey(ipKey)) {
            ipInRecord = (Map<String, List<IpRecord>>) redisTemplate.opsForValue().get(ipKey);
            ipLists = ipInRecord.get(ip);
            ipLists.add(ipRecord);
            //次数大于60
            //1.获取当前时间一分钟以前oneMin
            long oneMinuteAgo = now - 60 * 1000;
            List<IpRecord> tmp = ipLists.stream().filter(record -> record.getInTime() > oneMinuteAgo).collect(Collectors.toList());
            //2.获取大于oneMin的数据，且判断其长度是否大于访问限制->60
            if (tmp.size() > BaseConstant.LIMIT_IN_TIMES) {
                recordToBeBanIp.put(ip, recordToBeBanIp.getOrDefault(ip, 1) + 1);
                throw new SelfException("500", "TOO MANY REQUEST IN SHORT TIME,PLEASE TRY AGAIN ONE-MINUTE LATER");
            } else {
                recordToBeBanIp.remove(ip);
            }
            redisTemplate.opsForValue().set(ipKey, ipInRecord);
        } else {
            ipLists.add(ipRecord);
            ipInRecord.put(ip, ipLists);
            redisTemplate.opsForValue().set(ipKey, ipInRecord);

        }
        redisTemplate.opsForValue().set(RedisUtil.getInWebIps(), inIps);
    }

    public List<String> getBanIps() {
        List<String> banIps = (List<String>) redisTemplate.opsForValue().get(RedisUtil.getBanIp());
        if (CollectionUtil.isEmpty(banIps)) {
            banIps = new ArrayList<>();
        }
        return banIps;
    }

    public boolean judgeIpIsBan(String ip) {
        List<String> banIp = getBanIps();
        return banIp.contains(ip);
    }

    public Map<String, Long> getInIps() {
        Map<String, Long> inIps = (Map<String, Long>) redisTemplate.opsForValue().get(RedisUtil.getInWebIps());
        if (CollectionUtil.isEmpty(inIps)) {
            inIps = new HashMap<>();
        }
        return inIps;
    }
}
